封包式游戏功能的原理与实现
The following article is from 信安之路 Author 鬼手56
目录
前言
封包式功能的实现步骤
定位发包函数
三大发包函数
重写发包函数
线程发包
线程发包的形态和特点
条件断点筛出心跳包
线程发包的传参方式
跳出线程发包
定位加密封包内容
线程发包总结
定位明文发包函数
定位封包加密call
定位封包加密call
封包加密call参数分析
复制封包加密函数
调用函数实现功能
1. 定位到游戏的发包函数
2. 通过发包函数定位到明文发包函数
3. 通过明文发包函数定位到封包加密函数
4. 复制整个封包加密函数到自己的dll
5. 组包调用游戏功能
>>>> 三大发包函数
三大发包函数
send();
sendto();
WSASend();
1. 明明对send()函数下断了,却断不下来
2. 由于游戏中存在一个发包线程,所以即使断下send()函数,也无法回溯出有用的逻辑。
>>>> 重写发包函数
重写发包函数
1. 寻找send()函数内调用的底层函数,对底层函数下断。
send sendto和WSASend在底层都会调用一个函数叫WSPSend,F7进入send函数,第三个调用的call就WSPSend函数。
2. 搜索send函数的特征,定位到重写的send函数
>>>> 线程发包
线程发包
线程发包的形态和特点
1. 发包函数断的很频繁
2. 任何功能在发包函数断下,调用堆栈都是一样的
条件断点筛出心跳包
int WSAAPI WSASend(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
typedef struct _WSABUF {
ULONG len; //包长
CHAR *buf; //包内容
} WSABUF, *LPWSABUF;
[[esp+8]]!=11&&[[esp+8]]!=7
线程发包的传参方式
LPVOID g_addr=0;
functions()
{
//给地址赋值
g_addr=xxxxx;
//创建线程发包
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)send, g_addr, 0, 0);
}
functions()
{
//申请堆空间
wchar_t* lpaddr=new wchar_t[sizof(buff)];
//将包内容拷贝到堆空间
memcpy(lpaddr,buff,sizof(buff))
//创建线程发包
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)send, lpaddr, 0, 0);
}
跳出线程发包
定位加密封包内容
包内容=[[edx]+8]+4]
>>>> 线程发包总结
线程发包总结
1. 对于重写发包函数的问题,只需要在三个发包函数的底层函数下断或者搜索内层的特征码即可找到游戏重写的发包函数。
2. 对于线程发包的问题,需要找到数据包的地址来源,然后对基地址下写入断点。重复这个过程,即可跳出线程发包函数。
>>>> 定位封包加密call
定位封包加密call
>>>> 封包加密call参数分析
封包加密call参数分析
[[[00f84ba4]+4]+0xC+8]+54
__declspec(naked) void Encrypt(DWORD key,DWORD len,DWORD addr1,DWORD addr2)
{
__asm
{
push ebp
push ebx
push esi
push edi
mov edi, dword ptr [esp+0x14]
mov edx, dword ptr [esp+0x18]
mov esi, dword ptr [esp+0x1C]
mov ebp, dword ptr [esp+0x20]
xor eax, eax
xor ebx, ebx
cmp edx, 0
je Label1
mov al, byte ptr [edi]
mov bl, byte ptr [edi+4]
add edi, 8
lea ecx, dword ptr [esi+edx]
sub ebp, esi
mov dword ptr [esp+0x18], ecx
inc al
cmp dword ptr [edi+0x100], -1
je Label2
mov ecx, dword ptr [edi+eax*4]
and edx, 0xFFFFFFFC
je Label3
lea edx, dword ptr [esi+edx-4]
mov dword ptr [esp+0x1C], edx
mov dword ptr [esp+0x20], ebp
Label4:
add bl, cl
mov edx, dword ptr [edi+ebx*4]
mov dword ptr [edi+ebx*4], ecx
mov dword ptr [edi+eax*4], edx
add edx, ecx
inc al
and edx, 0x0FF
mov ecx, dword ptr [edi+eax*4]
mov ebp, dword ptr [edi+edx*4]
add bl, cl
mov edx, dword ptr [edi+ebx*4]
mov dword ptr [edi+ebx*4], ecx
mov dword ptr [edi+eax*4], edx
add edx, ecx
inc al
and edx, 0x0FF
ror ebp, 8
mov ecx, dword ptr [edi+eax*4]
or ebp, dword ptr [edi+edx*4]
add bl, cl
mov edx, dword ptr [edi+ebx*4]
mov dword ptr [edi+ebx*4], ecx
mov dword ptr [edi+eax*4], edx
add edx, ecx
inc al
and edx, 0x0FF
ror ebp, 8
mov ecx, dword ptr [edi+eax*4]
or ebp, dword ptr [edi+edx*4]
add bl, cl
mov edx, dword ptr [edi+ebx*4]
mov dword ptr [edi+ebx*4], ecx
mov dword ptr [edi+eax*4], edx
add edx, ecx
inc al
and edx, 0x0FF
ror ebp, 8
mov ecx, dword ptr [esp+0x20]
or ebp, dword ptr [edi+edx*4]
ror ebp, 8
xor ebp, dword ptr [esi]
cmp esi, dword ptr [esp+0x1C]
mov dword ptr [ecx+esi], ebp
lea esi, dword ptr [esi+4]
mov ecx, dword ptr [edi+eax*4]
jb Label4
cmp esi, dword ptr [esp+0x18]
je Label5
mov ebp, dword ptr [esp+0x20]
Label3:
add bl, cl
mov edx, dword ptr [edi+ebx*4]
mov dword ptr [edi+ebx*4], ecx
mov dword ptr [edi+eax*4], edx
add edx, ecx
inc al
and edx, 0x0FF
mov edx, dword ptr [edi+edx*4]
xor dl, byte ptr [esi]
lea esi, dword ptr [esi+1]
mov ecx, dword ptr [edi+eax*4]
cmp esi, dword ptr [esp+0x18]
mov byte ptr [ebp+esi-1], dl
jb Label3
jmp Label5
Label2:
movzx ecx, byte ptr [edi+eax]
Label6:
add bl, cl
movzx edx, byte ptr [edi+ebx]
mov byte ptr [edi+ebx], cl
mov byte ptr [edi+eax], dl
add dl, cl
movzx edx, byte ptr [edi+edx]
add al, 1
xor dl, byte ptr [esi]
lea esi, dword ptr [esi+1]
movzx ecx, byte ptr [edi+eax]
cmp esi, dword ptr [esp+0x18]
mov byte ptr [ebp+esi-1], dl
jb Label6
Label5:
dec al
mov byte ptr [edi-4], bl
mov byte ptr [edi-8], al
Label1:
pop edi
pop esi
pop ebx
pop ebp
retn
}
}
void :SendAnnounce()
{
byte a[100] = {0x11,0x00,0x7E,0x00,0x00,0x00,0x00,0x02,0x00,0x31,0x31,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x60,0xA8,0x6C};
DWORD datalen = 0x13;
DWORD data = (DWORD)a;
DWORD addr = data + 2;
DWORD addrlen = datalen - 2;
DWORD key = 0;
__asm
{
mov ecx,0x00f84ba4
mov ecx,[ecx]
mov ecx,[ecx]
mov ecx,[ecx+0x4]
mov ecx,[ecx+0x14]
mov ecx,[ecx]
lea ecx,[ecx+0x54]
mov key,ecx
}
Encrypt(key,addrlen,addr,addr);
HWND hWnd =FindWindowA("Lapis Network Class",0);
DWORD A = GetWindowLongW(hWnd,-21);
DWORD S =*(DWORD*)(A+0x38);
send(S,(const char*)data,datalen,0);
}
https://github.com/TonyChen56/GameReverseNote
看雪ID:鬼手56
https://bbs.pediy.com/user-833057.htm
推荐文章++++
好书推荐